package com.hermeneute.st.base;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class FileCharArray extends FileByteArray {
	Charset charset = Charset.forName("ISO-8859-1");
	CharsetDecoder decoder = charset.newDecoder();
	CharBuffer cb = null;
	int start = 0;
	int fault = 0;

	public FileCharArray(String fileName, int nob) throws IOException {
		super(fileName, nob);
	}

	public FileCharArray(String fileName, int nob, String mode)
			throws IOException {
		super(fileName, nob, mode);
	}

	char charAt(int p) throws CharacterCodingException, IOException {
		int offset = 0;
		if (cb != null) {
			// offset = p % cb.capacity();
			offset = p % bufferSize;
			if (start == p - offset && cb != null) {
				return cb.get(offset);
			} else {
				// System.out.println("change "+size()+" "+p+" "+offset);
				if (p >= size()) {
					throw new IndexOutOfBoundsException(p + " >= " + size());
				} else {
					cb = decoder.decode(getBuffer(p));
					 //System.out.println("new buffer "+cb.capacity()+" "+cb.limit()+" "+cb.position());
					start = p - offset;
					return cb.get(offset);
				}
			}
		} else {
			if (p >= size()) {
				throw new IndexOutOfBoundsException(p + " >= " + size());
			} else {
				cb = decoder.decode(getBuffer(p));
				// offset = p % cb.capacity();
				offset = p % bufferSize;
				start = p - offset;
				return cb.get(offset);
			}
		}
	}

	void setCharAt(int p, char ch) throws IOException {
		int offset = 0;
		if (cb != null) {
			offset = p % cb.capacity();
			if (start == p - offset && cb != null) {
				cb.put(offset, ch);
			} else {
				if (p >= size()) {
					throw new IndexOutOfBoundsException(p + " >= " + size());
				} else {
					cb = decoder.decode(getBuffer(p));
					start = p - offset;
					cb.put(offset, ch);
				}
			}
		} else {
			if (p >= size()) {
				throw new IndexOutOfBoundsException(p + " >= " + size());
			} else {
				cb = decoder.decode(getBuffer(p));
				offset = p % cb.capacity();
				start = p - offset;
				cb.put(offset, ch);
			}
		}
	}

	// F:\DigitalPhilology
	// C:\Documents and Settings\Administrator\Desktop\HeartOfDarkness.txt
	// C:\Documents and Settings\Administrator\Desktop\Bible.txt
	// C:\Documents and Settings\Administrator\Desktop\Aziyade.txt
	public static void test(int nob, FileByteArray.Policy p,int spread) throws IOException {
		FileCharArray fca = new FileCharArray(
				"C:\\Documents and Settings\\Administrator\\Desktop\\Bible.txt",
				nob, "r");
		fca.setPolicy(p);
		// 299008
		if (p == Policy.LRU) System.out.println("LRU");
		if (p == Policy.MRU) System.out.println("MRU");
		if (p == Policy.RANDOM) System.out.println("RANDOM");
		System.out.println(fca.size()+" "+fca.bufferSize+ " vms = "+fca.vms+" "+(1024*512)+" nob = "+fca.nob);
		long top = System.currentTimeMillis();
		for (int i = 0; i < fca.size(); i++) {
			int pos = (int) Math.floor(Math.random() * spread);
			int sign = (int) Math.floor(Math.random() * 2);
		
			if (sign == 0 && i + pos < fca.size())
				fca.charAt(i + pos);
			else if (sign == 0 && i + pos >= fca.size())
				fca.charAt(i );
			if (sign == 1 && i - pos >= 0)
				fca.charAt(i - pos);
			else if (sign == 1 && i - pos < 0)
				fca.charAt(i);
			// System.out.print(fca.charAt(i));
		}
		long top1 = System.currentTimeMillis() - top;
		System.out.println(top1 + " " + fca.faults);

		for (int i = (int) fca.size() - 1; i >= 0 ; i--) {
			int pos = (int) Math.floor(Math.random() * spread);
			int sign = (int) Math.floor(Math.random() * 2);
			if (sign == 0 && i + pos < fca.size())
				fca.charAt(i + pos);
			if (sign == 1 && i - pos >= 0)
				fca.charAt(i - pos);
			// System.out.print(fca.charAt(i));
		}
		long top2 = System.currentTimeMillis() - top;
		System.out.println((top2-top1) + " " + fca.faults + " vms = "+(long)fca.vms);
	}
	public static void test2(int nob, FileByteArray.Policy p) throws IOException {
		FileCharArray fca = new FileCharArray(
				"C:\\Documents and Settings\\Administrator\\Desktop\\Bible.txt",
				nob, "r");
		fca.setPolicy(p);
		// 299008
		if (p == Policy.LRU) System.out.println("LRU");
		if (p == Policy.MRU) System.out.println("MRU");
		if (p == Policy.RANDOM) System.out.println("RANDOM");
		System.out.println(fca.size()+" "+fca.bufferSize+ " vms = "+fca.vms+" "+(1024*512)+" nob = "+fca.nob);
		long top = System.currentTimeMillis();
		for (int i = 0; i < fca.size(); i++) {
				fca.charAt(i );
		}
		long top1 = System.currentTimeMillis() - top;
		System.out.println(top1 + " " + fca.faults);
	}
	public static void main(String[] args) throws IOException {
		test2(10,FileByteArray.Policy.LRU);
		test2(10,FileByteArray.Policy.RANDOM);
		test2(100,FileByteArray.Policy.LRU);
		test2(100,FileByteArray.Policy.RANDOM);
		test2(1200,FileByteArray.Policy.LRU);
		test2(1200,FileByteArray.Policy.RANDOM);
		test(10,FileByteArray.Policy.LRU,20*1024);
		test(10,FileByteArray.Policy.RANDOM,20*1024);
		test(100,FileByteArray.Policy.LRU,200*1024);
		test(100,FileByteArray.Policy.RANDOM,200*1024);
		test(1000,FileByteArray.Policy.LRU,2000*1024);
		test(1000,FileByteArray.Policy.RANDOM,2000*1024);
		test(1200,FileByteArray.Policy.LRU,2400*1024);
		test(1200,FileByteArray.Policy.RANDOM,2400*1024);
	}
}
